package com.platform.modules.auth.controller;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import com.platform.common.aspectj.IgnoreAuth;
import com.platform.common.aspectj.SubmitRepeat;
import com.platform.common.constant.AppConstants;
import com.platform.common.enums.YesOrNoEnum;
import com.platform.common.exception.BaseException;
import com.platform.common.shiro.ShiroLoginAuth;
import com.platform.common.shiro.ShiroLoginPhone;
import com.platform.common.shiro.utils.Md5Utils;
import com.platform.common.utils.redis.RedisUtils;
import com.platform.common.version.ApiVersion;
import com.platform.common.version.VersionEnum;
import com.platform.common.web.controller.BaseController;
import com.platform.common.web.domain.AjaxResult;
import com.platform.modules.auth.vo.AuthVo01;
import com.platform.modules.auth.vo.AuthVo02;
import com.platform.modules.auth.vo.AuthVo03;
import com.platform.modules.auth.vo.AuthVo04;
import com.platform.modules.chat.domain.ChatUser;
import com.platform.modules.chat.service.ChatUserService;
import com.platform.modules.sms.enums.SmsTypeEnum;
import com.platform.modules.sms.service.SmsService;
import com.platform.modules.sms.vo.SmsVo;
import com.platform.modules.wallet.domain.Wallet;
import com.platform.modules.wallet.domain.WalletTransfer;
import com.platform.modules.wallet.enums.IdentityStatusEnum;
import com.platform.modules.wallet.service.WalletService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 认证
 */
@RestController
@Slf4j
@RequestMapping("/auth")
public class AuthController extends BaseController {

    @Autowired
    private RedisUtils redisUtils;
    @Resource
    private ChatUserService chatUserService;
    @Resource
    private SmsService smsService;
    @Resource
    private WalletService walletService;

    /**
     * 发送验证码（登录/注册/忘记密码）
     */
    @IgnoreAuth
    @ApiVersion(VersionEnum.V1_0_0)
    @PostMapping(value = "/sendCode")
    @SubmitRepeat
    public AjaxResult sendCode(@Validated @RequestBody SmsVo smsVo) {
        return AjaxResult.success(smsService.sendSms(smsVo)).put("msg", "验证码已发送");
    }

    /**
     * 注册方法
     */
    @IgnoreAuth
    @ApiVersion(VersionEnum.V1_0_0)
    @PostMapping(value = "/register")
    public AjaxResult register(@Validated @RequestBody AuthVo01 authVo) {
        boolean match = ReUtil.isMatch("^[a-zA-Z0-9_\\u4e00-\\u9fa5]+$", authVo.getNickName());
        if (!match){
            return AjaxResult.fail("昵称不能含有特殊符号");
        }
        // 验证
        smsService.verifySms(authVo.getPhone(), authVo.getCode(), SmsTypeEnum.REGISTERED);
        // 注册
        chatUserService.register(authVo);

        chatUserService.registerMall(authVo);


        return AjaxResult.successMsg("注册成功，请登录");
    }

    /**
     * 注册测试号
     */
    @IgnoreAuth
    @ApiVersion(VersionEnum.V1_0_0)
    @PostMapping(value = "/registerTest")
    public AjaxResult registerTest() {

        long tel=13600000050l;

        AuthVo01 authVo = null;
//
        for (long i = tel; i<=13600000100l; i++){
            authVo=new AuthVo01().setPhone(String.valueOf(i))
                    .setPassword(Md5Utils.md5("888888"))
                    .setNickName(String.valueOf(i))
                    .setPortrait(AppConstants.DEFAULT_PORTRAIT);

            // 注册
            try {
                chatUserService.register(authVo);
                chatUserService.registerMall(authVo);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        for (long i = tel; i<13600000100l; i++) {
            ChatUser chatUser = chatUserService.queryByPhone(String.valueOf(i));
            chatUser.setPassLogin(YesOrNoEnum.YES);
            chatUserService.updateById(chatUser);
            Wallet wallet = walletService.getWallet(chatUser.getUserId());
            wallet.setPayPassword(Md5Utils.credentials(Md5Utils.md5("888888"),
                    chatUser.getSalt()))
                    .setName(RandomUtil.randomString(8))
                    .setIdentityCard("3324241"+i)
                    .setIdentityStatus(IdentityStatusEnum.YES);
            walletService.updateById(wallet);
            System.out.println(i);
        }

        return AjaxResult.successMsg("注册成功，请登录");
    }

    @IgnoreAuth
    @ApiVersion(VersionEnum.V1_0_0)
    @PostMapping("/login")
    public AjaxResult login(@Validated @RequestBody AuthVo02 authVo) {

        String lock_key = AppConstants.LOCK_PREFIX + "login:" + authVo.getPhone();
        if (redisUtils.hasKey(lock_key)){
            throw new BaseException("操作太频繁，请稍后再试");
        }
        redisUtils.set(lock_key,authVo.getPhone(),AppConstants.LOCK_EXPIRE, TimeUnit.SECONDS);

        ChatUser chatUser = chatUserService.queryOne(new ChatUser().setPhone(authVo.getPhone()));
        if (ObjectUtil.isNotEmpty(chatUser)){
            if (YesOrNoEnum.NO.equals(chatUser.getPassLogin())){
                throw new BaseException("账户不支持密码登录，请使用短信登录");
            }
        }

        // 执行登录
        ShiroLoginAuth loginAuth = new ShiroLoginAuth(authVo.getPhone(), authVo.getPassword());
        Dict dict = chatUserService.doLogin(loginAuth, authVo.getCid());
        redisUtils.expire(lock_key,AppConstants.LOCK_END, TimeUnit.SECONDS);

        return AjaxResult.success(dict);
    }

    /**
     * 登录方法（根据手机+验证码登录）
     */
    @IgnoreAuth
    @ApiVersion(VersionEnum.V1_0_0)
    @PostMapping("/loginByCode")
    public AjaxResult loginByCode(@Validated @RequestBody AuthVo03 authVo) {

        String lock_key = AppConstants.LOCK_PREFIX + "login:" + authVo.getPhone();
        if (redisUtils.hasKey(lock_key)){
            throw new BaseException("操作太频繁，请稍后再试");
        }
        redisUtils.set(lock_key,authVo.getPhone(),AppConstants.LOCK_EXPIRE, TimeUnit.SECONDS);
        // 验证
        smsService.verifySms(authVo.getPhone(), authVo.getCode(), SmsTypeEnum.LOGIN);
        // 执行登录
        ShiroLoginPhone loginPhone = new ShiroLoginPhone(authVo.getPhone());
        Dict dict = chatUserService.doLogin(loginPhone, authVo.getCid());
        return AjaxResult.success(dict);
    }

    /**
     * 找回密码（根据手机）
     */
    @IgnoreAuth
    @ApiVersion(VersionEnum.V1_0_0)
    @PostMapping("/forget")
    public AjaxResult forget(@Validated @RequestBody AuthVo04 authVo) {
        // 验证
        smsService.verifySms(authVo.getPhone(), authVo.getCode(), SmsTypeEnum.FORGET);
        // 查询用户
        ChatUser cu = chatUserService.queryByPhone(authVo.getPhone());
        if (cu == null) {
            throw new BaseException("手机号不存在");
        }
        // 重置密码
        chatUserService.resetPass(cu.getUserId(), authVo.getPassword());

        AuthVo01 authVo01 = new AuthVo01();
        authVo01.setPhone(authVo.getPhone());
        authVo01.setPassword(authVo.getPassword());
        chatUserService.resetPassMall(authVo01);
        return AjaxResult.successMsg("您的密码重置成功，请重新登录");
    }

}
